- catalina.out过大的定位过程&解决方案
 
场景记录
在一次mysql create table失败问题定位过程中,发现exitcode是28,即磁盘写失败导致的。可以参见这里,df -hk的查看结果是mysql所在分区100%usage。
问题定位过程
找到大文件
首先需要找到问题原因,即被什么文件吃满了disk。
du -sh / | sort -h
一直分析下去,可以定位到原因是catalina.out & flume的log比较大。
什么内容写入到catalina.out
catalina.out文件是tomcat的默认log方式,采用的是java.util.logging.Logging来控制的。其配置文件是:
[root@test-239 logs]# ps aux | grep java | grep logging
root     27130  0.9 12.4 4780116 998124 ?      Sl   04:01   4:42 java -Djava.util.logging.config.file=/usr/local/ahiddenpath/apache-tomcat-7.0.64/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.security.egd=file:/dev/./urandom -Djava.endorsed.dirs=/usr/local/ahiddenpath/apache-tomcat-7.0.64/endorsed -classpath /usr/local/ahiddenpath/apache-tomcat-7.0.64/bin/bootstrap.jar:/usr/local/ahiddenpath/apache-tomcat-7.0.64/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/ahiddenpath/apache-tomcat-7.0.64 -Dcatalina.home=/usr/local/ahiddenpath/apache-tomcat-7.0.64 -Djava.io.tmpdir=/usr/local/ahiddenpath/apache-tomcat-7.0.64/temp org.apache.catalina.startup.Bootstrap start
据上可知,配置文件在/usr/local/ahiddenpath/apache-tomcat-7.0.64/conf/logging.properties,查看其中内容:
handlers = 1catalina.org.apache.juli.FileHandler, 2localhost.org.apache.juli.FileHandler, 3manager.org.apache.juli.FileHandler, 4host-manager.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
.handlers = 1catalina.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
其中:
- FileHandler:输出log到指定文件
 - ConsoleHandler:输出log到console
 
在写demo验证logging.properties配置项的时候发现:
- java project默认是使用jre lib中的配置
 - path一般是jre/lib下面的logging.properties
 这个确实比较坑,改了半天配置都不生效,具体可以戳这里
另外一个比较蠢萌的点,是
-Djava.util.logging.config.file指定logging.properties位置的时候,-D需要在被运行的类之前,如:
- 这样是对的:java -Dxxx class
 - 这样是无效的:java class -Dxxx
 
除了catalina.out,tomcat还有什么其他日志
在看到文章:
- tomcat的几种log&version=12020810&nettype=WIFI&fontScale=100&pass_ticket=K7dxD3itvEIhOesfQoiCKNkkYFtbi28AIxNOKygQiPmzPpMpvzio45mY5vliTrfm)
 - tomcat 官方文档(6.0)关于日志的配置
 - oracle LogManager 类 API 文档
 
之后,对其中提到的 tomcat 的几种 log 做个总结:
- log 类型是
- catalina.out
 - cataliana.{yyyy-MM-dd}.log
 - localhost.{yyyy-MM-dd}.log
 - manager.{yyyy-MM-dd}.log
 - host-manager.{yyyy-MM-dd}.log
 
 - tomcat 可以改用log4j
 - console的内容会输出到 catalina.out,即
System.out.println()。 
更多的详细信息还是参见上面的三篇文档。
如何解决问题
为了避免这个问题,两种思路去限制:
- 修改配置本身不输出到catalina.out
 - 限制catalina.out的输出:log rotate
 
log rotate
- 这个文不错
- https://support.rackspace.com/how-to/sample-logrotate-configuration-and-troubleshooting/
 - 但修改了old folder之后,测试失败了,不知为何
 
 
是由cron触发的,定期执行的log切分程序。与log4j的文件拆分是有区别的,比如无法设置文件大小上限。
具体学习的话,可以参考文档:
- logrotate的机制与原理
- 戳这里
 - 核心内容:
- cron触发:
/etc/cron.daily/logrotate - 自定义在/etc/logrotate下面的conf,是通过/etc/logrotate.conf中的
include /etc/logrotate.d来触发的 - 另外文中还比较了create和copytruncate方案的原理
 
 - cron触发:
 
 - log rotate sample
 
修改logging配置文件
很简单,删除 ${catalina.base}/conf下面的logging.properties中的handlers= java.util.logging.ConsoleHandler即可。
这里举例是针对tomcat默认的logging.properties的位置,具体到其他项目,请具体查看
-Djava.util.logging.config.file的值
通过简单代码例子可知:
测试类代码:
package demo.maven;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
 * java util logging的测试类.
 * @author liruifeng
 * @see JavaUtilLoggingTest
 */
public class JavaUtilLoggingTest {
    private static final Logger logger = Logger.getLogger(JavaUtilLoggingTest.class.getName());
    public static void main(String args[]) {
        System.out.println(System.getProperty("java.util.logging.config.file"));
        System.out.println(System.getProperty("sss"));
        // Handler consoleHandler = new ConsoleHandler();
        // consoleHandler.setLevel(Level.ALL);
        // Logger.getAnonymousLogger().addHandler(consoleHandler);
        logger.setLevel(Level.ALL);
        System.out.println(logger.getLevel());
        logger.log(Level.ALL, "Level.ALL");
        logger.log(Level.FINE, "Level.FINE");
        logger.fine("fine");
        logger.log(Level.FINER, "Level.FINER");
        logger.log(Level.FINEST, "Level.FINEST");
        logger.log(Level.CONFIG, "Level.CONFIG");
        logger.log(Level.INFO, "Level.INFO");
        logger.info("info");
        logger.log(Level.WARNING, "Level.WARNING");
        logger.log(Level.SEVERE, "Level.SEVERE");
        logger.log(Level.OFF, "Level.OFF");
    }
}
原logging.properties(部分,在$jre_path/lib下面):
handlers=java.util.logging.ConsoleHandler
output:
null
null
ALL
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
全部: Level.ALL
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
详细: Level.FINE
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
详细: fine
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
较详细: Level.FINER
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
非常详细: Level.FINEST
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
配置: Level.CONFIG
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
信息: Level.INFO
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
信息: info
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
警告: Level.WARNING
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
严重: Level.SEVERE
五月 26, 2017 4:48:48 下午 demo.maven.JavaUtilLoggingTest main
禁用: Level.OFF
修改后的logging.properties
#handlers=java.util.logging.ConsoleHandler
对应output:
null
null
ALL
以上,测试生效